package rdbms

import (
	"database/sql"
	"strconv"
	"time"

	"github.com/golang/glog"

	_ "github.com/lib/pq" // pgsql driver
)

// PgsqlConnectParams database init params.
type PgsqlConnectParams struct {
	DBName         string
	User           string
	Password       string
	Host           string
	Port           int
	SSLMode        string
	ConnectTimeout int
	SSLCert        string
	SSLKey         string
	SSLRootCert    string
}

type pgsqlConnectManager struct{}

// NewPgsqlConnectManager new a database manager
func NewPgsqlConnectManager() ConnectManager {
	return new(pgsqlConnectManager)
}

func (inst *pgsqlConnectManager) Init(env *Env) (*sql.DB, error) {
	params, ok := env.ConnectParams.(PgsqlConnectParams)
	if !ok {
		glog.Fatalln("database connect parameters not set or type incorrect")
	}
	connStr := "dbname=" + params.DBName + " user=" + params.User
	if params.Password != "" {
		connStr += " password=" + params.Password
	}
	if params.Host != "" {
		connStr += " host=" + params.Host
	}
	if params.Port != 0 {
		connStr += " port=" + strconv.Itoa(params.Port)
	}
	if params.SSLMode != "" {
		connStr += " sslmode=" + params.SSLMode
	}
	if params.ConnectTimeout != 0 {
		connStr += " connect_timeout=" + strconv.Itoa(params.ConnectTimeout)
	}
	if params.SSLRootCert != "" {
		connStr += " sslrootcert=" + params.SSLRootCert
	}
	if params.SSLMode != "" {
		connStr += " sslcert=" + params.SSLCert
	}
	if params.SSLKey != "" {
		connStr += " sslkey=" + params.SSLKey
	}

	conn, err := sql.Open("postgres", connStr)
	if err != nil {
		glog.Fatalln(err)
	}
	if err = conn.Ping(); err != nil {
		glog.Fatalln(err)
	}
	if env.MaxIdle == 0 {
		conn.SetMaxIdleConns(2)
	}
	conn.SetMaxIdleConns(env.MaxIdle)
	if env.MaxOpen == 0 {
		conn.SetMaxOpenConns(10)
	}
	conn.SetMaxOpenConns(env.MaxOpen)
	if env.ConnMaxLifetime == 0 {
		conn.SetConnMaxLifetime(3 * time.Second)
	}
	conn.SetConnMaxLifetime(env.ConnMaxLifetime * time.Second)
	return conn, err
}

func (inst *pgsqlConnectManager) Destroy(conn *sql.DB) error {
	err := conn.Close()
	return err
}
